import time


from io import BytesIO
from itertools import islice
from typing import Any, Optional, List
import os
import oss2
import requests
from uuid import uuid4
from configs.conf import cfg
from components.logger import service_log


class Oss:
    def __init__(self) -> None:
        self.auth = oss2.Auth(cfg.oss.access_key, cfg.oss.secret_key)
        self.endpoint = cfg.oss.end_point
        self.bucket = oss2.Bucket(
            self.auth, self.endpoint, bucket_name=cfg.oss.bucket_name, connect_timeout=180
        )

    def get_bucket_list(self) -> List[str]:
        """列举当前endpoint下所有的bucket_name"""
        service = oss2.Service(self.auth, self.endpoint)
        bucket_list = [b.name for b in oss2.BucketIterator(service)]
        return bucket_list

    def get_all_files(self, prefix: str) -> List[str]:
        """获取指定前缀下所有文件"""
        return [
            b.key for b in islice(oss2.ObjectIterator(self.bucket, prefix=prefix), 10)
        ]

    def read_file(self, path: str) -> Optional[bytes]:
        """读取指定路径的文件内容"""
        try:
            key = path.replace(f"https://{cfg.oss.bucket_name}.{cfg.oss.end_point}/", '')
            file_info = self.bucket.get_object(key).read()
            return file_info
        except oss2.exceptions.NoSuchKey:
            service_log.error(f"文件 {path} 不存在")
        except Exception as e:
            service_log.error(f"读取文件 {path} 时出错: {e}")
        return None

    def exists_file(self, path: str) -> bool:
        """检查指定路径的文件是否存在"""
        try:
            key = path.replace(f"https://{cfg.oss.bucket_name}.{cfg.oss.end_point}/", '')
            return self.bucket.object_exists(key)
        except Exception as e:
            service_log.error(f"检查文件 {path} 存在性时出错: {e}")
            return False

    def download_file(self, path: str, save_path: str) -> Optional[str]:
        """下载指定路径的文件到本地"""
        try:
            key = path.replace(f"https://{cfg.oss.bucket_name}.{cfg.oss.end_point}/", '')
            self.bucket.get_object_to_file(key, save_path)
            return save_path
        except oss2.exceptions.NoSuchKey:
            service_log.error(f"文件 {path} 不存在")
        except Exception as e:
            service_log.error(f"下载文件 {path} 时出错: {e}")
        return None

    def upload_file(
            self, ext: str, local_path: str, file_name: Optional[str] = None
    ) -> Optional[str]:
        """上传本地文件到OSS"""
        if not file_name:
            file_name = f"{cfg.oss.file_dir}{str(uuid4())}{ext}"
        try:
            result = self.bucket.put_object_from_file(file_name, local_path)
            if result.status == 200:
                return f"https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}"
        except Exception as e:
            service_log.error(f"上传文件 {local_path} 到 {file_name} 时出错: {e}")
        return None

    def upload_all_file(self, ext: str, data: Any) -> Optional[str]:
        """上传数据到OSS"""
        file_name = f"{cfg.oss.file_dir}{str(uuid4())}{ext}"
        try:
            self.bucket.put_object(file_name, data)
            return f"https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}"
        except Exception as e:
            service_log.error(f"上传数据到 {file_name} 时出错: {e}")
        return None

    def upload_remote_file(
            self, file_url: str, ext: str, file_name: Optional[str] = None,**kwargs
    ) -> Optional[str]:
        """上传远程文件到OSS"""

        if not file_name:
            file_name = f"{cfg.oss.file_dir}{str(uuid4())}{ext}"
        try:
            if 'http' not in file_url:
                file_url = file_url.replace(':', '').replace('//', '')
                file_url = 'http://' + file_url
            response = requests.get(file_url, stream=True, headers={
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36'
                , **kwargs})

            response.raise_for_status()
            self.bucket.put_object(file_name, response.content)

            return f"https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}"
        except requests.exceptions.RequestException as e:
            service_log.error(f"下载远程文件 {file_url} 时出错: {e}")
        except Exception as e:
            service_log.error(f"上传远程文件 {file_url} 到 {file_name} 时出错: {e}")
        return None

    def upload_from_stream(
            self, ext: str, stream: BytesIO, file_name: Optional[str] = None
    ) -> Optional[str]:
        """从流中上传文件到OSS"""
        if not file_name:
            file_name = f"{cfg.oss.file_dir}{str(uuid4())}{ext}"
        try:
            self.bucket.put_object(file_name, stream.getvalue())
            return f"https://{cfg.oss.bucket_name}.{self.endpoint}/{file_name}"
        except Exception as e:
            service_log.error(f"从流中上传文件到 {file_name} 时出错: {e}")
        return None

    def delete_from_path(self, url,retry=0):
        try:
            if not url:
                return 0
            key =  url.split('aliyuncs.com/')[-1]

            # bucket_name: ai-video-digital
            # end_point: oss-accelerate.aliyuncs.com
            #oss-cn-shenzhen.aliyuncs.com  ai-video-writemall-com
            bucket_name = url.split('.')[0].split('://')[-1]
            endpoint = url.split('.aliyuncs.com')[0].split('.')[-1]+'.aliyuncs.com'
            bucket = oss2.Bucket(
                self.auth, endpoint, bucket_name=bucket_name, connect_timeout=180
            )
            res = bucket.delete_object(key)
            # if int(res) !=204 and retry<3:
            #     return self.delete_from_path(url, retry + 1)
            return res.status
        except Exception as e:
            service_log.error(f"删除出错: {e}{url}")
            time.sleep(.1)
            if retry<3:
                return self.delete_from_path(url,retry+1)
            return 0
    def copy_path(self,key,new_key):
        try:
            self.bucket.copy_object(self.bucket.bucket_name, key, new_key)
            return 'https://ai-video-digital.oss-accelerate.aliyuncs.com/'+new_key
        except:
            return ''


oss_object = Oss()

def get_oss() -> Oss:
    return Oss()

if __name__ == "__main__":
    oss = get_oss()

    # oss.copy_path('crawler/1134296613003896.jpg','11342781838.jpg')
    # oss.delete_from_path('crawler/000017b6-c547-42f6-a1f3-1b1964787c6c.jpeg')
    res = oss.delete_from_path(
# 'https://payment-writemall-com.oss-cn-shenzhen.aliyuncs.com/analysis-others/dymp4_6512326022484987140.mp4'
# 'https://ai-video-digital.oss-accelerate.aliyuncs.com/crawler/61636358-fa84-4042-a54c-31b000289506dymp3_6960698433157991715.mp3'
'https://ai-video-digital.oss-accelerate.aliyuncs.com/crawler/dymp4_7468661607040666940.mp4'
    )
    print(res)



    #
    # # 上传本地图片，使用自定义文件名
    # local_path = os.path.join(os.getcwd(), 'data', 'image', 'test.jpg')
    # file_name = cfg.oss.file_dir + str(uuid4()) + '.jpg'
    # url2 = oss.upload_file(local_path=local_path, file_name=file_name, ext='.jpg')
    # if url2:
    #     service_log.info(f"文件 {local_path} 上传到 {url2}")
    #
    # # 下载 bucket 下指定的 key
    # ext = url.split('.')[-1]
    # save_path = os.path.join(os.getcwd(), 'data', 'image', str(uuid4()) + '.' + ext)
    # saved_path = oss.download_file(url, save_path)
    # service_log.info(f"文件 {url} 下载到 {saved_path}")
    #
    # # 检测文件是否存在
    # if oss.exists_file(url2):
    #     service_log.info(f"文件 {url2} 存在")
    #
    # # 读取文件流
    # file_info = oss.read_file(url2)
    #
    # # 上传文件流
    # url3 = oss.upload_from_stream(ext='.jpg', stream=BytesIO(file_info))
    # service_log.info(f"文件流上传到 {url3}")
    #
    # # 上传远程文件到 oss
    # url4 = oss.upload_remote_file(
    #     file_url=url3,
    #     ext='.jpg',
    # )
    # service_log.info(f"远程文件 {url3} 上传到 {url4}")
